package com.rk.recommand;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.*;

public class UserCF_Step3 {
    public static class Step3Mapper extends Mapper<LongWritable, Text, Text, Text>{
        Text k = new Text();
        Text v = new Text();

        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();
            String[] words = CommonConst.DELIMITER.split(line);
            if(words.length >= 3){
                k.set(words[0]);
                v.set(words[1] + "," + words[2]);
                context.write(k, v);
            }
        }
    }

    public static class Step3Reducer extends Reducer<Text, Text, Text, Text> {
        private final int NEIGHBORHOOD_NUM = 2;

        @Override
        public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
            Map<Double, String> map = new HashMap<Double, String>();

            for (Text line : values) {
                String val = line.toString();
                String[] words = CommonConst.DELIMITER.split(val);

                if (words.length >= 2) {
                    map.put(Double.parseDouble(words[1]), words[0]);
                }
            }

            List<Double> list = new ArrayList<Double>();
            Iterator<Double> iter = map.keySet().iterator();
            while (iter.hasNext()) {
                Double similarity = iter.next();
                list.add(similarity);
            }

            //然后通过比较器来实现排序
            Collections.sort(list, new Comparator<Double>() {
                //降序排序
                public int compare(Double o1, Double o2) {
                    return o2.compareTo(o1);
                }
            });

//            for (int i = 0; i < NEIGHBORHOOD_NUM && i < list.size(); i++)
//            {
//        		context.write(key, new Text(map.get(list.get(i)) + "," + String.format("%.7f", list.get(i))));
//            }

            String v = "";
            for (int i = 0; i < NEIGHBORHOOD_NUM && i < list.size(); i++) {
                v += "," + map.get(list.get(i)) + "," + String.format("%.7f", list.get(i));
            }

            context.write(key, new Text(v.substring(1)));

        }
    }

    public static void run(Map<String, String> paths) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration configuration = new Configuration();
        System.setProperty("HADOOP_USER_NAME", "root");
        configuration.set("mapreduce.job.jar", "D:\\projects\\hadoop-study\\target\\hadoop-study-1.0-SNAPSHOT-jar-with-dependencies.jar");
        configuration.set("mapreduce.app-submission.cross-platform", "true");//意思是跨平台提交

        String input = paths.get("input_step3");
        String output = paths.get("output_step3");

        // 本地运行的话 无需在hdfs创建目录 否则需要使用hdfs API
        Job job = Job.getInstance(configuration, "UserCF_Step3 job");
        job.setJarByClass(UserCF_Step3.class);
        job.setMapperClass(Step3Mapper.class);
        job.setReducerClass(Step3Reducer.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        FileInputFormat.setInputPaths(job, new Path(input));
        FileOutputFormat.setOutputPath(job, new Path(output));

        boolean result = job.waitForCompletion(true);
        if(result){
            System.out.println("UserCF_Step3 run successful");
        }else {
            System.out.println("UserCF_Step3 run failed");
        }
    }
}
